package com.corewillsoft.fireflies.storage;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

import android.database.Cursor;

import com.corewillsoft.fireflies.gameobjects.Firefly;
import com.corewillsoft.fireflies.gameobjects.GameObject;
import com.corewillsoft.fireflies.gameobjects.Portal;
import com.corewillsoft.fireflies.gameobjects.obstacles.Obstacle;
import com.corewillsoft.fireflies.gameobjects.obstacles.Obstacle.ObstacleParameters;
import com.corewillsoft.fireflies.storage.entries.MapLevelEntries;
import com.corewillsoft.fireflies.storage.entries.SavedGameLevelEntries;
import com.corewillsoft.fireflies.storage.entries.StartGameLevelEntries;
import com.corewillsoft.fireflies.storage.objects.BaseGameLevel;
import com.corewillsoft.fireflies.storage.objects.MapLevel;
import com.corewillsoft.fireflies.storage.objects.SavedGameLevel;
import com.corewillsoft.fireflies.storage.objects.StartGameLevel;
import com.corewillsoft.fireflies.util.TypesConverter;

final class ObjectsConverter {

	private ObjectsConverter() {
	}

	static MapLevel convertMapLevelFromCursor(Cursor cursor) {
		int level = cursor.getInt(cursor
				.getColumnIndex(MapLevelEntries.LEVEL));
		int x = cursor.getInt(cursor.getColumnIndex(MapLevelEntries.X));
		int y = cursor.getInt(cursor.getColumnIndex(MapLevelEntries.Y));
		int width = cursor.getInt(cursor.getColumnIndex(MapLevelEntries.WIDTH));
		int height = cursor.getInt(cursor.getColumnIndex(MapLevelEntries.HEIGHT));
		String imageRef = cursor.getString(cursor
				.getColumnIndex(MapLevelEntries.IMAGE_REF));

		return new MapLevel(level, x, y, width, height, imageRef);
	}

	static BaseGameLevel convertToSaveGameLevel(Cursor cursor) {
		BaseGameLevel gameLevel = new SavedGameLevel(convertToStartGameLevel(cursor));

		String fireflyEnergy = cursor.getString(cursor.getColumnIndex(SavedGameLevelEntries.FIREFLY_ENERGY));
		gameLevel.setFireflyEnergy(TypesConverter.stringToFloatList(fireflyEnergy));

		String fireflyAlive = cursor.getString(cursor.getColumnIndex(SavedGameLevelEntries.FIREFLY_ALIVE));
		gameLevel.setFireflyAlive(TypesConverter.stringToBooleanList(fireflyAlive));

		String fireflySaved = cursor.getString(cursor.getColumnIndex(SavedGameLevelEntries.FIREFLY_SAVED));
		gameLevel.setFireflySaved(TypesConverter.stringToBooleanList(fireflySaved));

		return gameLevel;
	}

	static BaseGameLevel convertToStartGameLevel(Cursor cursor) {
		BaseGameLevel gameLevel = new StartGameLevel();

		int level = cursor.getColumnIndex(StartGameLevelEntries.LEVEL);
		gameLevel.setLevel(cursor.getInt(level));

		String fireflyIds = cursor.getString(cursor.getColumnIndex(StartGameLevelEntries.FIREFLY_IDS));
		gameLevel.setFireflyIds(TypesConverter.stringToIntegerList(fireflyIds));

		String fireflyX = cursor.getString(cursor.getColumnIndex(StartGameLevelEntries.FIREFLY_X));
		gameLevel.setFireflyX(TypesConverter.stringToIntegerList(fireflyX));

		String fireflyYs = cursor.getString(cursor.getColumnIndex(StartGameLevelEntries.FIREFLY_Y));
		gameLevel.setFireflyY(TypesConverter.stringToIntegerList(fireflyYs));

		String portalIds = cursor.getString(cursor.getColumnIndex(StartGameLevelEntries.PORTAL_IDS));
		gameLevel.setPortalIds(TypesConverter.stringToIntegerList(portalIds));

		String portalX = cursor.getString(cursor.getColumnIndex(StartGameLevelEntries.PORTAL_X));
		gameLevel.setPortalX(TypesConverter.stringToIntegerList(portalX));

		String portalY = cursor.getString(cursor.getColumnIndex(StartGameLevelEntries.PORTAL_Y));
		gameLevel.setPortalY(TypesConverter.stringToIntegerList(portalY));

		String obstacleIds = cursor.getString(cursor.getColumnIndex(StartGameLevelEntries.OBSTACLE_IDS));
		gameLevel.setObstacleIds(TypesConverter.stringToIntegerList(obstacleIds));

		String obstacleX = cursor.getString(cursor.getColumnIndex(StartGameLevelEntries.OBSTACLE_X));
		gameLevel.setObstacleX(TypesConverter.stringToIntegerList(obstacleX));

		String obstacleY = cursor.getString(cursor.getColumnIndex(StartGameLevelEntries.OBSTACLE_Y));
		gameLevel.setObstacleY(TypesConverter.stringToIntegerList(obstacleY));

		String obstaclesParameters = cursor.getString(cursor.getColumnIndex(StartGameLevelEntries.OBSTACLES_PARAMS));
		int obstaclesCount = gameLevel.getObstacleIds().size();
		gameLevel.setObstaclesParameters(gameLevel.stringToObstaclesParameters(obstaclesParameters, obstaclesCount));

		return gameLevel;
	}

	static BaseGameLevel getGameLevel(int level, Set<GameObject> gameObjects) {
		BaseGameLevel gameLevel = new SavedGameLevel();
		gameLevel.setLevel(level);

		addFireflies(gameObjects, gameLevel);
		addPortals(gameObjects, gameLevel);
		addObstacles(gameObjects, gameLevel);

		return gameLevel;
	}

	private static void addObstacles(Set<GameObject> gameObjects, BaseGameLevel gameLevel) {
		List<Integer> obstacleIds = new ArrayList<Integer>();
		gameLevel.setObstacleIds(obstacleIds);
		List<Integer> obstacleX = new ArrayList<Integer>();
		gameLevel.setObstacleX(obstacleX);
		List<Integer> obstacleY = new ArrayList<Integer>();
		gameLevel.setObstacleY(obstacleY);
		List<ObstacleParameters> obstaclesParameters = new ArrayList<ObstacleParameters>();
		gameLevel.setObstaclesParameters(obstaclesParameters);

		for (GameObject gameObject : gameObjects) {
			if (gameObject instanceof Obstacle) {
				Obstacle obstacle = (Obstacle) gameObject;
				if (obstacle.getType() != null) {
					obstacleIds.add(obstacle.getType().ordinal());
				}
				obstacleX.add((int) obstacle.getX());
				obstacleY.add((int) obstacle.getY());
				obstaclesParameters.add(obstacle.getParametersMap());
			}
		}
	}

	private static void addPortals(Set<GameObject> gameObjects, BaseGameLevel gameLevel) {
		List<Integer> portalX = new ArrayList<Integer>();
		gameLevel.setPortalX(portalX);
		List<Integer> portalY = new ArrayList<Integer>();
		gameLevel.setPortalY(portalY);
		List<Integer> portalIds = new ArrayList<Integer>();
		gameLevel.setPortalIds(portalIds);

		for (GameObject gameObject : gameObjects) {
			if (gameObject instanceof Portal) {
				Portal portal = (Portal) gameObject;
				portalIds.add(portal.getRace().ordinal());
				portalX.add((int) portal.getX());
				portalY.add((int) portal.getY());
			}
		}
	}

	private static void addFireflies(Set<GameObject> gameObjects, BaseGameLevel gameLevel) {
		List<Integer> fireflyIds = new ArrayList<Integer>();
		gameLevel.setFireflyIds(fireflyIds);
		List<Integer> fireflyX = new ArrayList<Integer>();
		gameLevel.setFireflyX(fireflyX);
		List<Integer> fireflyY = new ArrayList<Integer>();
		gameLevel.setFireflyY(fireflyY);
		List<Float> fireflyEnergy = new ArrayList<Float>();
		gameLevel.setFireflyEnergy(fireflyEnergy);
		List<Boolean> fireflySaved = new ArrayList<Boolean>();
		gameLevel.setFireflySaved(fireflySaved);
		List<Boolean> fireflyAlive = new ArrayList<Boolean>();
		gameLevel.setFireflyAlive(fireflyAlive);

		for (GameObject gameObject : gameObjects) {
			if (gameObject instanceof Firefly) {
				Firefly firefly = (Firefly) gameObject;
				if (firefly.getRace() != null) {
					fireflyIds.add(firefly.getRace().ordinal());
				}
				fireflyX.add((int) firefly.getX());
				fireflyY.add((int) firefly.getY());
				fireflyEnergy.add(firefly.getEnergy());
				fireflySaved.add(firefly.isSaved());
				fireflyAlive.add(firefly.isAlive());
			}
		}
	}
}
